#include <47func.h>

//printf("i am feature1!");
int epollAdd(int epfd, int fd){
    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = fd; 
    epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&event);
    return 0;
}
int epollDel(int epfd, int fd){
    struct epoll_event event;
    event.events = EPOLLIN;
    event.data.fd = fd; 
    epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&event);
    return 0;
}   


typedef struct train_s {
    int length;
    char data[1000];//上限是1000个字节
}train_t;
//int recvFile(int sockfd){
//    // 先收文件名
//    //char filename[1024] = {0};
//    //recv(sockfd,filename,sizeof(filename),0);
//    //int fd = open(filename,O_RDWR|O_CREAT,0666);
//    //char buf[4096] = {0};
//    //ssize_t sret = recv(sockfd,buf,sizeof(buf),0);
//    //write(fd,buf,sret);
//    //close(fd);
//    train_t train;
//    bzero(&train,sizeof(train));
//    recv(sockfd,&train.length,sizeof(train.length),0);//先收四个字节
//    recv(sockfd,train.data,train.length,0);//再一个train.length的长度
//    int fd = open(train.data,O_RDWR|O_CREAT,0666);
//    bzero(&train,sizeof(train));
//    recv(sockfd,&train.length,sizeof(train.length),0);//先收四个字节
//    recv(sockfd,train.data,train.length,0);//再一个train.length的长度
//    write(fd,train.data,train.length);
//    close(fd);
//    return 0;
//}
int recvn(int sockfd, void *buf, int length){
    int total = 0;
    int ret;
    char *p = (char *)buf;
    while(total < length){
        ret = recv(sockfd,p+total,length-total,0);
        total += ret;
    }
    return 0;
}
//int recvFile(int sockfd){
//    // 先收文件名
//    train_t train;
//    bzero(&train,sizeof(train));
//    //recv(sockfd,&train.length,sizeof(train.length),MSG_WAITALL);//先收四个字节
//    //recv(sockfd,train.data,train.length,MSG_WAITALL);//再一个train.length的长度
//    recvn(sockfd,&train.length,sizeof(train.length));
//    recvn(sockfd,train.data,train.length);
//    int fd = open(train.data,O_RDWR|O_CREAT,0666);
//    while(1){
//        bzero(&train,sizeof(train));
//        //recv(sockfd,&train.length,sizeof(train.length),MSG_WAITALL);//先收四个字节
//        recvn(sockfd,&train.length,sizeof(train.length));//先收四个字节
//        if(train.length != 1000){
//            printf("train.length = %d\n",train.length);
//        }
//        if(train.length == 0){
//            break;
//        }
//        //recv(sockfd,train.data,train.length,MSG_WAITALL);//再一个train.length的长度
//        recvn(sockfd,train.data,train.length);//再一个train.length的长度
//        write(fd,train.data,train.length);
//    }
//    close(fd);
//    return 0;
//}
int recvFile(int sockfd){
    // 先收文件名
    train_t train;
    bzero(&train,sizeof(train));
    recvn(sockfd,&train.length,sizeof(train.length));
    recvn(sockfd,train.data,train.length);
    int fd = open(train.data,O_RDWR|O_CREAT,0666);
    off_t filesize;
    recvn(sockfd,&train.length,sizeof(train.length));
    recvn(sockfd,&filesize,train.length);
    printf("filesize = %ld\n", filesize);
    off_t cursize = 0;
    off_t lastsize = 0;
    off_t slice = filesize/10000;
    while(1){
        bzero(&train,sizeof(train));
        //recv(sockfd,&train.length,sizeof(train.length),MSG_WAITALL);//先收四个字节
        recvn(sockfd,&train.length,sizeof(train.length));//先收四个字节
        if(train.length != 1000){
            printf("train.length = %d\n",train.length);
        }
        if(train.length == 0){
            break;
        }
        //recv(sockfd,train.data,train.length,MSG_WAITALL);//再一个train.length的长度
        recvn(sockfd,train.data,train.length);//再一个train.length的长度
        write(fd,train.data,train.length);
        cursize += train.length;
        if(cursize - lastsize > slice ){
            printf("%5.2lf%%\r",100.0*cursize/filesize);
            fflush(stdout);
            lastsize = cursize;
        }
    }
    printf("100.00%%\n");
    close(fd);
    return 0;
}
//int recvFile(int sockfd){
//    // 先收文件名
//    train_t train;
//    bzero(&train,sizeof(train));
//    recvn(sockfd,&train.length,sizeof(train.length));
//    recvn(sockfd,train.data,train.length);
//    int fd = open(train.data,O_RDWR|O_CREAT,0666);
//    off_t filesize;
//    recvn(sockfd,&train.length,sizeof(train.length));
//    recvn(sockfd,&filesize,train.length);
//    printf("filesize = %ld\n", filesize);
//    // 建立映射区
//    ftruncate(fd,filesize);
//    char *p = (char *)mmap(NULL,filesize,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
//    ERROR_CHECK(p,MAP_FAILED,"mmap");
//    recvn(sockfd,p,filesize);
//    munmap(p,filesize);
//    close(fd);
//    return 0;
//}


int transFile(int netfd,char *filename){
    train_t train;
    train.length = strlen(filename);
    memcpy(train.data,filename,train.length);//组装第一列小火车
    //发送小火车
    send(netfd,&train,sizeof(train.length)+train.length,MSG_NOSIGNAL);
    int fd = open(filename,O_RDWR);
    struct stat statbuf;
    // 获取文件大小
    fstat(fd,&statbuf);
    // 发送小火车 火车头 size的长度 火车车厢 size的内容
    bzero(&train,sizeof(train));
    train.length = sizeof(statbuf.st_size);
    memcpy(train.data,&statbuf.st_size,train.length);
    send(netfd,&train,sizeof(train.length)+train.length,MSG_NOSIGNAL);
    // 使用mmap
    char *p = (char *)mmap(NULL,statbuf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    ERROR_CHECK(p,MAP_FAILED,"mmap");
    off_t totalsize = 0;//记录已经发送的长度
    while(totalsize < statbuf.st_size){
        if(statbuf.st_size - totalsize > (long )sizeof(train.data)){
            train.length = sizeof(train.data); // 剩余数据超过火车车厢的上限
        }   
        else{
            train.length = statbuf.st_size - totalsize;
        }   
        send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
        send(netfd,p+totalsize,train.length,MSG_NOSIGNAL);
        totalsize += train.length;
    }   
    //补发一个空火车
    train.length = 0;                                                                       
    send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);
    munmap(p,statbuf.st_size);
    close(fd);
    return 0;
}








int main(int argc, char *argv[])
{
    // ./client 192.168.118.128 1234
    ARGS_CHECK(argc,3);
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr(argv[1]);
    serverAddr.sin_port = htons(atoi(argv[2]));
    int ret = connect(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr));
    ERROR_CHECK(ret,-1,"connect");
    //recvFile(sockfd);
    char buf[1024];
    fd_set rdset;
    while(1)
    {

        FD_ZERO(&rdset);
        FD_SET(STDIN_FILENO,&rdset);
        FD_SET(sockfd,&rdset);
        select(sockfd+1,&rdset,NULL,NULL,NULL); 

            if( FD_ISSET(STDIN_FILENO,&rdset)) 
            {
                memset(buf,0,sizeof(buf));
                read(STDIN_FILENO,buf,sizeof(buf));
                send(sockfd,buf,sizeof(buf),0);
                char cmd[10]={0};
                char filename[1024]={0};
                sprintf(cmd,"%s",strtok(buf," "));
                sprintf(filename,"%s",strtok(NULL," "));
                if(strncmp("puts\0",cmd,4) == 0)
                {
                    char sendfilename[32]={0};
                    char *rootpath = getcwd(NULL,0);
                    char sendcontent[1024]={0};
                    printf("准备发送文件！\n");
                    send(sockfd,"1",1,0);
                    
                    for(unsigned long i=0;i<strlen(filename)-1;i++)
                    {
                        sendfilename[i]=filename[i];
                    }
                    sprintf(sendcontent,"%s/%s",rootpath,sendfilename);
                    printf("%s\n",sendcontent);
                    //transFile(sockfd,sendcontent);
                    //transFile(sockfd,)
                }
                printf("发送成功！\n");
            }
            else if(FD_ISSET(sockfd,&rdset)) //对面发来消息
            {
                memset(buf,0,sizeof(buf));
                ssize_t sret = recv(sockfd,buf,sizeof(buf),0);
                if(strcmp("1\0",buf) == 0)
                {
                    printf("我接收到了！\n");
                    recvFile(sockfd);
                }
                //判断是否exit
                if(sret == 0)
                { 
                    printf("客户端关闭！\n");
                    sleep(1);
                }

                //普通接收到的消息
                printf("%s\n",buf);
            }

    }

    return 0;
}

